package com.wlc.collection;


import java.util.*;

/**
 * @author 王立朝 wanglichao@champion-credit.com
 * @description 序列
 * @date 2021-07-11 16:52
 */
public class LinkListDemo {

    /**
     * LinkedList 在链表头部和链表尾部插入数据和移除数据很方便
     */
    public void method01() {
        LinkedList linkedList = new LinkedList();
        linkedList.add("1");
        linkedList.add("2");
        linkedList.add("3");
        // 在头部添加数据
        linkedList.addFirst("0");
        // 在尾部添加数据
        linkedList.addLast("4");
        linkedList.forEach(System.out::println);
        // 移除头部数据
        linkedList.removeFirst();
        // 移除尾部数据
        linkedList.removeLast();
        System.out.println("========");
        linkedList.forEach(System.out::println);


    }

    public void method02() {
        Queue queue = new LinkedList<>();
        queue.add("1");
        queue.add("2");
        queue.add("3");
        // 1、 queue.peek()  返回队列的头部,但是不会把数据从队列中移除掉
        Object peek = queue.peek();
        System.out.println("peek = " + peek);
        System.out.println("queue.peek 只是拿出来看看，不会把数据移除->" + queue);
        // 2、 queue.poll()  取出队列中的第一个数据；会把数据从头部移除
        Object poll = queue.poll();
        System.out.println("poll = " + poll);
        System.out.println("queue.poll 会把队列中的数据移除 = " + queue);

        // 3、在队列的最后一个添加数据
        queue.offer("666");
        System.out.println("queue.peek() = " + queue.peek());
        Object element = queue.element();
        System.out.println("element = " + element);
        System.out.println("queue = " + queue);
    }

    /**
     * 测试 ArrayList和 LinkedList 哪一种插入数据比较快
     */
    public void method03() {
        List<Integer> number = null;
        number = new ArrayList<>();
        addNumber(number, "ArrayList");
        number = new LinkedList<>();
        addNumber(number, "LinkedList");
    }

    /**
     * 在ArrayList 和 LinkedList 的头部追加100000 条数据，计算时间
     * 结果表明：  ArrayList 大概需要 460毫秒
     * LinkedList 大概需要5毫秒
     *
     * @param list
     * @param type
     */
    public void addNumber(List<Integer> list, String type) {
        int total = 1000 * 100;
        long start = System.currentTimeMillis();
        for (int i = 0; i < total; i++) {
            list.add(0, i);
        }
        long end = System.currentTimeMillis();
        System.out.printf("在 %s类型的 list 集合的头部追加 1000000  耗时%d", type, end - start);
        System.out.println("");
    }

    /**
     * 定位到5000的数据，然后在这个数据之后再加入一个数据，循环100000次
     */
    public void method04() {
        List<Integer> list = null;
        list = new ArrayList<>();
        modifyList(list, "ArrayList");
        list = new LinkedList<>();
        modifyList(list, "LinkedList");
    }

    /**
     * 在LinkedList 和 ArrayList  中间 新增一个数据，取出来，再放进去，循环
     * 10000次， ArrayList 耗时 小于LinkedList
     *
     * @param list
     * @param type
     */
    public void modifyList(List<Integer> list, String type) {
        int total = 1000 * 100;
        final int number = 5;
        int index = total / 2;
        // 初始化list
        for (int i = 0; i < total; i++) {
            list.add(number);
        }
        long start = System.currentTimeMillis();

        for (int i = 0; i < total; i++) {

            Integer integer = list.get(index);
            integer++;
            list.add(index, integer);
        }

        long end = System.currentTimeMillis();
        System.out.printf("在%s 类型的第 %d 位置的数据取出来加一，并放回去，循环100000次， 耗时为： %d 毫秒", type, index, end - start);
        System.out.println("  ");
    }

    /**
     * 在ArrayList 和 linkedList 尾部分别插入一条数据，循环10000次，分别计算耗时
     */
    public void method05() {
        List<Integer> list;
        list = new ArrayList<>();
        modifyLast(list, "ArrayList");
        list = new LinkedList<>();
        modifyLast(list, "LinkedList");
    }

    /**
     * 在尾部添加数据，ArrayList 也很快； LinkedList 不管是中间还是尾部，添加数据都是很快的
     *
     * @param list
     * @param type
     */
    public void modifyLast(List<Integer> list, String type) {
        int total = 1000 * 100;
        ;
        final int number = 5;
        int index = total / 2;
        // 初始化list
        for (int i = 0; i < total; i++) {
            list.add(number);
        }
        long start = System.currentTimeMillis();

        for (int i = 0; i < total; i++) {
            // 在最后添加数据
            list.add(number);
        }

        long end = System.currentTimeMillis();
        System.out.printf("在%s 类型的集合中，循环100000次，在集合尾部添加数据， 耗时为： %d 毫秒", type, end - start);
        System.out.println("  ");
    }

    public static void main(String[] args) {
        LinkListDemo linkList = new LinkListDemo();
        linkList.method05();
    }
}
